<template>
  <a-modal v-bind="curModalOptions" v-model:open="curVisible" @ok="onModalOk">
    <div class="bw-js-extnd-modal">
      <div class="bw-js-extnd-param-box">
        <div class="bw-js-extnd-param-title">
          <span>表达式参数</span>
          <a-button size="small" type="primary" @click="onAddParams">
            新增
          </a-button>
        </div>

        <BwJsExtndParam
          ref="codeParam"
          :eventParams="curEventParams"
          :params="curParams"
          @delete="onDelParam"
        />
      </div>

      <div class="bw-js-extnd-content-box">
        <div class="js-content" ref="codeEdit"></div>
      </div>
    </div>
  </a-modal>
</template>

<script lang="ts" setup>
import * as monaco from 'monaco-editor'
import BwMonacoEditor from '@/utils/monacoEditor'
import { ref, unref, toRaw, computed, nextTick, watch } from 'vue'

import BwJsExtndParam from './params/index.vue'

import type { BwCurNodeEventInfoModel } from '../model'
import type { BwCustomComNodeEventCallbackParamInfoModel } from '@bitwit/base-com-render'
interface BwJsExtndProps {
  visible: boolean
  data: BwCurNodeEventInfoModel | null
}

const bwMonacoEditor = new BwMonacoEditor()
const emit = defineEmits(['update:visible', 'ok'])
const props = withDefaults(defineProps<BwJsExtndProps>(), {
  visible: false,
})

const codeEdit = ref()
const codeParam = ref()
const curValue = ref<string>('')
const curParams = ref<BwCustomComNodeEventCallbackParamInfoModel[]>([])
const curVisible = computed({
  get: () => props.visible,
  set: (value) => emit('update:visible', value),
})

const curEventParams = computed(() => {
  const info = props.data
  return info?.eventParams ?? []
})

const curModalOptions = computed(() => {
  return {
    zIndex: 1010,
    title: '表达式定义',
    wrapClassName: 'bw-custom-com-preview',
  }
})

const curEditor = ref<monaco.editor.IStandaloneCodeEditor | undefined>()
const initMonacoEditor = (value?: string) => {
  curValue.value = value ?? 'export default {\n  extnd (params) {\n  }\n}'
  curEditor.value = bwMonacoEditor.create({
    menus: undefined,
    snippets: undefined,
    domElement: unref(codeEdit),
    options: {
      value: unref(curValue),
      wordWrap: 'on',
      language: 'typescript',
    },
  })

  /** 监听编辑器内容变化 */
  const curEdit = unref(curEditor)
  if (curEdit) {
    curEdit.onDidChangeCursorPosition(function (e) {
      if (curEdit) {
        let readOnly = false
        if (e.position.lineNumber <= 2) {
          readOnly = true
        }
        toRaw(curEdit).updateOptions({
          readOnly: readOnly,
        })
      }
    })

    curEdit.onDidChangeModelContent(() => {
      try {
        const curText = toRaw(curEdit).getValue()
        curValue.value = curText
      } catch (error) {
        console.warn('编辑器报错')
      }
    })
  }
}

/** 新增表达式参数 */
const onAddParams = () => {
  curParams.value?.push({} as BwCustomComNodeEventCallbackParamInfoModel)
}

const onDelParam = (index: number) => {
  const list = curParams.value ?? []

  list.splice(index, 1)
  curParams.value = list
}

const onModalOk = () => {
  const ele = unref(codeParam)
  const params = ele.getParamList()
  const info = props.data ?? {}
  curVisible.value = false
  emit('ok', {
    ...info,
    callbackFun: unref(curValue),
    callbackFunParams: params,
  })
}

watch(
  () => curVisible.value,
  (newVal) => {
    if (newVal) {
      nextTick(() => {
        const { callbackFun, callbackFunParams } = props.data ?? {}

        curParams.value = callbackFunParams ?? []
        initMonacoEditor(callbackFun)
      })
    }
  },
  { deep: true, immediate: true }
)
</script>

<style lang="less" scoped>
.bw-js-extnd-modal {
  width: 80vw;
  height: 60vh;
  overflow: auto;
  min-width: 1024px;
  min-height: 400px;
  display: flex;
  flex-direction: column;

  .bw-js-extnd-param-box {
    flex-shrink: 0;
    min-width: 1024px;
    width: calc(100% - 48px);

    .bw-js-extnd-param-title {
      width: 100%;
      display: flex;
      margin-bottom: 5px;
      justify-content: space-between;

      span {
        font-weight: 600;
      }
    }
  }

  .bw-js-extnd-content-box {
    flex: 1;
    flex-shrink: 0;
    margin-top: 8px;
    min-height: 200px;
    border-radius: 5px;
    width: calc(100% - 48px);
    border: 1px solid #e8e8e8;
    overflow: auto;

    .js-content {
      width: 100%;
      height: 100%;
    }
  }
}
</style>
